/* WiFi station Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "lwip/err.h"
#include "lwip/sys.h"
/*-------------------- */
#include "lwip/sockets.h"

//#include <cJSON.h>
/*---------uartheadfile----------- */
#include "driver/uart.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_log.h"
/*----for chip info----*/
#include "esp_chip_info.h"
#include "esp_heap_caps.h"
#include <esp_spi_flash.h>
/*----------serialdata process------------ */
#include "serialdata.h"
#include "semaphoreTest.h"

extern void Button_Gpio_Init(void);
extern void Buttonsatus_Print(void);

//#define ENVIRONMENT_OUT 1
#define ENVIRONMENT_HOME 1 


/**
 * 这个程序，你可以理解成一个  <串口-->UDP传输模块> 
 * 对于ESP32外部输入有串口屏、gpio(按键、编码器)、IIc(陀螺仪-待添加),这些外部输入
 * 都可以转化为串口数据，然后统一由udp发送至上位机
 * 
 */
/**
 * @brief 
 *         WiFi启动流程：
 *         1.串口屏通过串口发送命令(关键字、ssid、password、目标ip、目标port)
 *         2.串口收到数据后调用Process_Command(data,len)函数，对命令进行解析
 *         3.Process_Command里状态机调用   parse_credentials(rawframe+PACKETHEAD_POSITION)拆解ssid、password等，
 *         然后调用wifi_init_callback,然后调用wifi_init_sta启动WiFi
 *         4.wifi启动成功后，创建udp socket，随后进入"等待发送状态"
 **/

/**
 * 
 **/
char wifiinfo_ssid[33]="lsy330586";
char wifiinfo_password[33]="sfz402176";
char wifiinfo_destaddr[17]="192.168.0.101";
char wifiinfo_port[7]="777";
int  wifinfo_portnum=777;

#define EXAMPLE_ESP_WIFI_SSID      "default_wifi_ssid"
#define EXAMPLE_ESP_WIFI_PASS      "default_password"

#define EXAMPLE_ESP_MAXIMUM_RETRY  CONFIG_ESP_MAXIMUM_RETRY

#if CONFIG_ESP_WPA3_SAE_PWE_HUNT_AND_PECK
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK
#define EXAMPLE_H2E_IDENTIFIER ""
#elif CONFIG_ESP_WPA3_SAE_PWE_HASH_TO_ELEMENT
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HASH_TO_ELEMENT
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#elif CONFIG_ESP_WPA3_SAE_PWE_BOTH
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#endif
#if CONFIG_ESP_WIFI_AUTH_OPEN
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
#elif CONFIG_ESP_WIFI_AUTH_WEP
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
#endif

/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;
void creatsocket_Callback();

//wifi事件组，目前只有两个：连接事件、断开事件
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1

static const char *TAG = "wifi station";

static int s_retry_num = 0;
/** 
 * @brief  事件handler，在这里处理各种WIFI事件的逻辑 
 * @param
 * @return none
 **/
static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();//注意哦在这里connect
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
            esp_wifi_connect();
            s_retry_num++;
            ESP_LOGI(TAG, "retry to connect to the AP");
        } else {
            xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
        }
        ESP_LOGI(TAG,"connect to the AP fail");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
        s_retry_num = 0;
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
    }
}


//用于标记wifi时间组是否成功注册
esp_event_handler_instance_t s_instance_any_id = NULL;
esp_event_handler_instance_t s_instance_got_ip = NULL;
void user_wifi_deinit() {
   if (s_wifi_event_group != NULL) {
        vEventGroupDelete(s_wifi_event_group);
        s_wifi_event_group = NULL;
    }

    esp_err_t err = ESP_OK;
    wifi_mode_t current_mode;

    // Check if Wi-Fi is already initialized
    err = esp_wifi_get_mode(&current_mode);
    if (err == ESP_OK && current_mode != WIFI_MODE_NULL) {
        // Wi-Fi is already initialized, stop and deinit
        ESP_ERROR_CHECK(esp_wifi_stop());
        ESP_ERROR_CHECK(esp_wifi_deinit());
    }

    // Unregister all event handlers
    if (s_instance_any_id != NULL) {
        ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, s_instance_any_id));
        s_instance_any_id = NULL;
    }
    if (s_instance_got_ip != NULL) {
        ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, s_instance_got_ip));
        s_instance_got_ip = NULL;
    }
}


void creatsocket_Callback();

/**
 * @brief wiif初始化函数
 * @param ssid
 * @param password  
 * @return none
 **/
bool s_event_loop_created = false;  // 标记是否已经创建了事件循环
void wifi_init_sta(char* ssid,char *password)
{

   // 由于该函数由于外部的串口命令触发，调用前要先判断一下WiFi当前的状态，
   // 如果已经连接了WiFi需要先停止
    ESP_LOGI(TAG, "Starting WiFi init task");
    user_wifi_deinit();
    s_wifi_event_group = xEventGroupCreate();

    if (!s_event_loop_created) {
        ESP_ERROR_CHECK(esp_netif_init());
        ESP_ERROR_CHECK(esp_event_loop_create_default());
        esp_netif_create_default_wifi_sta();
        s_event_loop_created = true;
    }

     /*------------------------------------------------------------------------*/
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_got_ip));
    /*------------------------------------------------------------------------*/
    wifi_config_t wifi_config =
    {
        .sta = {
            //.ssid = {0},//这个char str[]和 “xxxx”是不是还是区别挺大？
            //.password = {0},
            .ssid = EXAMPLE_ESP_WIFI_SSID,
            .password = EXAMPLE_ESP_WIFI_PASS,
            .threshold.authmode = WIFI_AUTH_WPA_PSK,
            .sae_pwe_h2e = ESP_WIFI_SAE_MODE,
            .sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,
        },
    };
    if (strlen(ssid) + 1 <= sizeof(wifi_config.sta.ssid)) {
        strcpy((char*)wifi_config.sta.ssid, ssid);
    }

        if (strlen(password) + 1 <= sizeof(wifi_config.sta.password)) {
        strcpy((char*)wifi_config.sta.password, password);
    }


    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
    /*------------------------------------------------------------------------*/
    ESP_ERROR_CHECK(esp_wifi_start() );
    ESP_LOGI(TAG, "wifi_init_sta finished.");
    /*------------------------------------------------------------------------*/
    /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
     * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
    EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
            WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
            pdFALSE,
            pdFALSE,
            portMAX_DELAY);

    /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
     * happened. */
    if (bits & WIFI_CONNECTED_BIT) {
        //ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
        ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", wifi_config.sta.ssid, wifi_config.sta.password);
        /***如果连接成功，则创建socket***/ 
        creatsocket_Callback();
    } else if (bits & WIFI_FAIL_BIT) {
        ESP_LOGI(TAG, "xxxx-Failed to connect to SSID:%s, password:%s", wifi_config.sta.ssid, wifi_config.sta.password);
        //ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", wifi_config.sta.ssid, wifi_config.sta.password);
    } else {
        ESP_LOGE(TAG, "UNEXPECTED EVENT");
    }

    
}

/**
 * @brief 
 * @param
 * @return none
 **/
static void WifiInit_task(void *pvParameters)
{
   // wifi_init_sta(wifi_ssid,wifi_password);
    static int cnt=5;
    while(cnt>1)
    {

         printf("WifiInit_task running:%d\r\n",cnt--);
         vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
   printf("---task delet\r\n");
   //xSemaphoreGive(WifiInit_MutexSemaphore);//给信号量，允许重新初始化wifi
   vTaskDelete(NULL);// ???delet如何实现的？进入该函数之后是不是就被调度了？
}

/*-------------------------------------*/
static SemaphoreHandle_t WifiInit_BinarySemaphore;
void create_wifiinit_semaphore(void)
{
    WifiInit_BinarySemaphore = xSemaphoreCreateBinary(); // 创建一个二进制信号量
    xSemaphoreGive(WifiInit_BinarySemaphore);
    static int cnt;
    while(1)
    {
            //if(xSemaphoreTake(sync_taskB, portMAX_DELAY)==pdTRUE)
            if(xSemaphoreTake(WifiInit_BinarySemaphore, 0)==pdTRUE)
            {
            // printf("TaskB Take Semaphore,%d\n",task_B_runcnt++);
                printf("main.c WifiInit_BinarySemaphore  running,%d\n",cnt++);
            }else
            {
                 printf("main.c WifiInit_BinarySemaphore  running,%d\n",cnt++);
            }
        
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}

/**
 * @brief 
 * @param
 * @return none
 **/
void wifi_init_callback(char* ssid,char *password)
{
     xSemaphoreGive(WifiInit_BinarySemaphore);
}

/**
 * @brief 
 * @param
 * @return none
 **/
/*
*调试函数：
* 以assic形式打印数据
*
*/
/*
void printAsciiArray(const unsigned char *asciiArray, size_t length) {
    for (size_t i = 0; i < length; i++) {
        //printf("Character: '%c' | ASCII Value: %d\n", asciiArray[i], asciiArray[i]);
        if (i > 0 && i % 10 == 0) { // 在每次循环开始时检查换行，除了第一次
            printf("\n");
        }
         printf(" 0x%02x ", asciiArray[i]);
    }
    if (length % 10 != 0) { // 如果最后一行不足10个字符，也需要换行
        printf("\n");
    }
}*/
void printAsciiArray(const void *data, size_t length, int isUnsigned) {
    const unsigned char *ucharData = (const unsigned char *)data;
    const char *charData = (const char *)data;

    for (size_t i = 0; i < length; i++) {
        if (i > 0 && i % 10 == 0) { // 在每次循环开始时检查换行，除了第一次
            printf("\n");
        }

        if (isUnsigned) {
            printf(" 0x%02x ", ucharData[i]);
        } else {
            printf(" 0x%02x ('%c') ", (unsigned char)charData[i], charData[i]);
        }
    }

    if (length % 10 != 0) { // 如果最后一行不足10个字符，也需要换行
        printf("\n");
    }
}

/********************创建一个队列，用于将串口数据发送给UDP任务**********************/
QueueHandle_t uart_to_udp_queue;


#define CONFIG_EXAMPLE_IPV4 1
//static const char *payload_src = "Message from ESP32-20240708";

/**
 * @brief 创建UDP客户端任务，创建成功后，在while（1）循环中等待uart_to_udp_queue
 *        是否有数据，若有数据则发送
 * @param
 * @return none
 **/
static void udp_client_task(void *pvParameters)
{
    //char rx_buffer[128];
    //char host_ip[] = HOST_IP_ADDR;
    int addr_family = 0;
    int ip_protocol = 0;

    
    while (1) {

#if defined(CONFIG_EXAMPLE_IPV4)
        struct sockaddr_in dest_addr;
        dest_addr.sin_addr.s_addr = inet_addr(wifiinfo_destaddr);
        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = htons(wifinfo_portnum);
        addr_family = AF_INET;
        ip_protocol = IPPROTO_IP;
#elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN)
        struct sockaddr_storage dest_addr = { 0 };
        ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_DGRAM, &ip_protocol, &addr_family, &dest_addr));
#endif
        int sock = socket(addr_family, SOCK_DGRAM, ip_protocol);
        if (sock < 0) {
            ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
            break;
        }

        // Set timeout
        struct timeval timeout;
        timeout.tv_sec = 10;
        timeout.tv_usec = 0;
        setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);

        ESP_LOGI(TAG, "Socket created, sending to %s : %d", wifiinfo_destaddr,  wifinfo_portnum);
        ESP_LOGI(TAG,"/*----------------after setsockopt----------------*/\r\n");
        printf("protnum:%d\r\n",wifinfo_portnum);
        static int udp_send_cnt=0;
        static char *payload[50]; 
        char* rx_buffer_ptr;

        //while (1){...}中等待uart_to_udp_queue队列中是否有数据(阻塞),直到接收到uart_task发来的数据
        //随后将数据通过sendto()发送
        while (1) {
#if 1
       
        if (xQueueReceive(uart_to_udp_queue, &rx_buffer_ptr, portMAX_DELAY) == pdTRUE) 
        {
            ESP_LOGI(TAG, "udp recieved");
            //printf("- get: %s -\r\n",rx_buffer_ptr);
            //printAsciiArray(rx_buffer_ptr,10);
           int err = sendto(sock, rx_buffer_ptr, strlen(rx_buffer_ptr), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
            if (err < 0) {
                ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
                break;
            }
        }
#endif
            vTaskDelay(1000 /portTICK_PERIOD_MS);
        }

        if (sock != -1) {
            ESP_LOGE(TAG, "Shutting down socket and restarting...");
            shutdown(sock, 0);
            close(sock);
        }
    }
    vTaskDelete(NULL);
}


/******************************************* 
    WIFI启动成功后调用
 *******************************************/
void creatsocket_Callback()
{
    xTaskCreate(udp_client_task, "client_task",4096, NULL, 5, NULL);
}


/**
 * @brief 串口相关宏定义
 * 串口号：UART-1
 * tx引脚：gpio_17,
 * rx引脚: gpio_18,
 * 波特率：115200, 
 **/
#define ECHO_TEST_TXD (17)
#define ECHO_TEST_RXD (18)
#define ECHO_TEST_RTS (-1)
#define ECHO_TEST_CTS (-1)

#define ECHO_UART_PORT_NUM      (1)
#define ECHO_UART_BAUD_RATE     (115200)
#define ECHO_TASK_STACK_SIZE    (CONFIG_EXAMPLE_TASK_STACK_SIZE)
#define SENDCNT_LEN (4)
static const char *UARTTAG = "UART TEST";

#define BUF_SIZE (128)
#define UARTREAD_WAIT (100)
char uart_buffer[BUF_SIZE];

/******************************************* 
    echo_task：串口接受数据，将数据转发到队列
 *******************************************/

void sendtoUdp_Callback(char* data)
{
     //printAsciiArray(data,10);
     printf("before xqueuesend\r\n");
     if (xQueueSend(uart_to_udp_queue,&data, portMAX_DELAY) == pdPASS)
      {
               // ESP_LOGI(TAG, "Data sent to UDP task");
    }
}
/**
 * @brief  uart任务,初始化uart之后，在while循环中 uart_read_bytes不断的轮询串口
 *         收到数据后，交给 Process_Command(_,_)函数去处理
 * @param
 * @return none
 **/
static void uart_task(void *arg)
{
    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    uart_config_t uart_config = {
        .baud_rate = ECHO_UART_BAUD_RATE,
        .data_bits = UART_DATA_8_BITS,
        .parity    = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_DEFAULT,
    };
    int intr_alloc_flags = 0;

#if CONFIG_UART_ISR_IN_IRAM
    intr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endif

    ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
    ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config));
    ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS));

    // Configure a temporary buffer for the incoming data
    char *data = (char *) malloc(128);
    static const char *TAG2 = "From ESP32 Uart2:";
    int tag2len=strlen(TAG2);
    static int sendcnt=0;
    char sendcnt_char[SENDCNT_LEN]={0};
    while (1) {
        //memset(uart_buffer, 0, sizeof(uart_buffer));
        int len = uart_read_bytes(ECHO_UART_PORT_NUM, uart_buffer, (BUF_SIZE - 1), UARTREAD_WAIT / portTICK_PERIOD_MS);  
        //uart_write_bytes(ECHO_UART_PORT_NUM, (const char *) data, len);
        if (len) 
        {
            
            memset(data, 0, 128);
            
           ESP_LOGI(TAG, "uart recieve:\r\n");
          
          memcpy(data,uart_buffer,len);
         // printAsciiArray(data,len,0);
          //这个函数用于接收data(字符串命令)，解析关键字之后进行处理操作
          Process_Command(data,len);
        //我不太想把这个queuesend放到这个函数里，
        /*  if (xQueueSend(uart_to_udp_queue,&uartbuffer_ptr, portMAX_DELAY) == pdPASS)
           {
               // ESP_LOGI(TAG, "Data sent to UDP task");
           }
         */  
        }
        
        vTaskDelay(pdMS_TO_TICKS(1));
    }
}

void receiver_task(void *pvParameters)
{
    unsigned char* rx_message;
    while (1)
    {
       // printf("wait for uart_to_udp_queue\r\n");
        if (xQueueReceive(uart_to_udp_queue, &rx_message, portMAX_DELAY) == pdPASS)
        {
            ESP_LOGI(TAG, "receiver_task: \r\n" );
            printAsciiArray( rx_message,10,0);
            // 释放内存
            //free(rx_message);
        }
        vTaskDelay(5 / portTICK_PERIOD_MS);
    }
}

/**
 * @brief 主任务，任务中创建"串口队列"、串口任务、初始化gpio(按键、旋钮编码器...)
 *        在while(1){...}中做任务管理，如创建删除wifi连接任务、任务信息打印、gpio口信息打印等
 * @param
 * @return none
 **/
void app_main(void)
{
    //Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    //创建串口队列，接收后的数据通过队列发送给UDP任务
    uart_to_udp_queue = xQueueCreate(5, sizeof(char*));
    xTaskCreate(uart_task, "uart_task",4096, NULL, 6, NULL);
    //初始化按键的io口
    Button_Gpio_Init();
    //semaphore_main( );
#if 0
    WifiInit_BinarySemaphore = xSemaphoreCreateBinary(); // 创建一个二进制信号量
    xSemaphoreGive(WifiInit_BinarySemaphore);
    xSemaphoreTake(WifiInit_BinarySemaphore,portMAX_DELAY);

    static int cnt;
    static int get_semaphore=0;
    //任务管理
    while(1)
    {

        if(xSemaphoreTake(WifiInit_BinarySemaphore,0) == pdTRUE)
        {  
           wifi_init_sta(wifiinfo_ssid,wifiinfo_password);
           get_semaphore++;
           ESP_LOGI(TAG, "---get WifiInit_BinarySemaphore\r\n");
       }else{
           ESP_LOGI(TAG, "---No WifiInit_BinarySemaphore\r\n");
       }

        printf("app_main running:%d\r\n",cnt++);
        vTaskDelay(2500 / portTICK_PERIOD_MS);
        Buttonsatus_Print();
    }
#endif
    static int cnt;
    //static int get_semaphore=0;
     wifi_init_sta(wifiinfo_ssid,wifiinfo_password);
     xTaskCreate(udp_client_task, "client_task",4096, NULL, 5, NULL);
    //任务管理
   
   //xTaskCreate(receiver_task, "recieve_task",2048, NULL, 6, NULL);
    while(1)
    {

        printf("app_main running:%d\r\n",cnt++);
        vTaskDelay(2500 / portTICK_PERIOD_MS);
        Buttonsatus_Print();
    }

}


/**
 * @brief 
 * @param
 * @return none
 **/

/*****************************************************************************/
/*****************************************************************************/

#if 0
static void udp_send_task(void *pvParameters)
{
    char host_ip[] = HOST_IP_ADDR;
    int addr_family = 0;
    int ip_protocol = 0;

    while (1) {

        struct sockaddr_in dest_addr;
        dest_addr.sin_addr.s_addr = inet_addr(HOST_IP_ADDR);
        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = htons(HOST_PORT);
        addr_family = AF_INET;
        ip_protocol = IPPROTO_IP;


        int sock = socket(addr_family, SOCK_DGRAM, ip_protocol);
        if (sock < 0) {
            ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
            break;
        }
        // Set timeout
        struct timeval timeout;
        timeout.tv_sec = 10;
        timeout.tv_usec = 0;
        setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);

        ESP_LOGI(TAG, "Socket created, sending to %s:%d", HOST_IP_ADDR, HOST_PORT);
        
        static int udp_send_cnt=0;
        static char *payload[50];
        //我想实现把 udp_send_cnt变量，添加到 payload里边
        
        char* rx_buffer_ptr;
        while (1) {

           
           int err = sendto(sock,payload_src, strlen(payload_src), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
            if (err < 0) {
                ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
                break;
            }
            printf("delaytest-%d\r\n",udp_send_cnt++);
            vTaskDelay(900 /portTICK_PERIOD_MS);
        }

        if (sock != -1) {
            ESP_LOGE(TAG, "Shutting down socket and restarting...");
            shutdown(sock, 0);
            close(sock);
        }
    }
    vTaskDelete(NULL);
}


// 接收任务
void receiver_task(void *pvParameters)
{
   char *rx_message;
   static int revcnt=0;
    while (1)
    {
        if (xQueueReceive(uart_to_udp_queue, &rx_message, portMAX_DELAY) == pdPASS)
        {
            //ESP_LOGI(TAG, "Rec: %s", rx_message);
            printf("-: %s-",rx_message);
            printf("    ,   -rcvcnt: %d\r\n",revcnt++);
            //printf("-%s ", rx_message+SENDCNT_LEN);
          
        }
           vTaskDelay(pdMS_TO_TICKS(1));
    }

}



void intToString(int number, char *str) {
    // Using sprintf for conversion
    sprintf(str, "%d", number);
}

void appendStringToBuffer(char *buffer, const char *newString) {
    // Append newString to buffer using strncat to prevent overflow
   // strncat(buffer, newString, sizeof(buffer) - strlen(buffer) - 1);
   strncat(buffer, newString, 5);
}

#endif